# 报告页相关接口
# 执行测试相关接口
import os
import psutil
import subprocess
import threading
import re
import shutil
import socket
from datetime import datetime
import time, yaml, json, paramiko
from itertools import cycle
from flask import Blueprint, request, send_file
from Logger import logger, logger_config
import xml.etree.ElementTree as ET
from utils import MyResponse, get_global_config, get_local_ip, handle_exception, handle_success, \
    compress_directory_to_zip
from utilsNetwork import execute_command_linux, check_jmeter_start


report = Blueprint('report', __name__)

# 创建一个字典来存储报告的执行状态和锁对象
report_status = {}

# 获取最新版本和历史版本的报告的URL
@report.route('/file/getReport', methods=['POST'])
def get_report():
    try:
        params = request.json
        print(params)
        root_path = get_global_config()['rootPath']
        project_dir = os.path.join(root_path, params["projectName"])
        local_ip = get_local_ip()
        # 初始化存储报告路径和历史报告路径的字典
        report_urls = {}
        # 初始化存储历史报告路径的列表
        history_report_urls = []
        # 获取目录下所有子目录名
        subdirectories = [name for name in os.listdir(project_dir) if os.path.isdir(os.path.join(project_dir, name))]
        # 过滤出以 "reportbak" 开头的子目录
        reportbak_directories = [name for name in subdirectories if name.startswith('reportbak')]
        print(f"-----------yuanshi:{reportbak_directories}")
        # 排序子目录
        sorted_directories = sorted(
            reportbak_directories,
            key=lambda dir_name: datetime.strptime(dir_name[9:], "%Y%m%d-%H%M%S"),
            reverse=True
        )
        print(sorted_directories)
        # 构建最新报告的URL
        report_url = ""
        report_path = os.path.join(root_path, params["projectName"], "report", "TestReport.html")
        if os.path.exists(report_path):
            report_url = f"http://{local_ip}/getReport/{params['projectName']}/report"

        # 构建历史报告的URL列表
        for directory in sorted_directories:
            history_report_path = os.path.join(root_path, params["projectName"], directory, "TestReport.html")
            if os.path.exists(history_report_path):
                history_report_url = f"http://{local_ip}/getReport/{params['projectName']}/{directory}"
                history_report_urls.append(history_report_url)

        # 如果没有最新报告，但有历史报告，则使用最新的历史报告作为报告URL
        if not report_url and history_report_urls:
            report_url = history_report_urls[0]

        # 存储报告路径和历史报告路径列表到字典中
        report_urls["report"] = report_url
        report_urls["history"] = history_report_urls

        # 检查报告是否存在
        if not report_urls.get("report"):
            return handle_exception("没有可用的报告", "没有可用的报告")

    except Exception as err:  # 捕获异常
        return handle_exception(err, "程序异常")
    else:
        return handle_success(report_urls, "success")


# 下载报告
@report.route('/file/downloadReport', methods=['POST'])
def download_report():
    try:
        params = request.json
        root_path = get_global_config()['rootPath']
        report_path = os.path.join(root_path, params["projectName"], params["reportDir"])
        output_zip = os.path.join(root_path, params["projectName"], f"{params['reportDir']}.zip")
        compress_directory_to_zip(report_path, output_zip)
        res = send_file(output_zip, as_attachment=True, download_name=params["reportDir"], mimetype="application/zip")
    except Exception as err:  # 捕获异常
        print(err)  # 打印异常参数
        res = MyResponse({"err": err}, False, "error").post()
        return res
    else:
        return res
# 返回值：data:"10.58.20.17"
@report.route('/file/getUserIP', methods=['GET'])
def get_user_ip():
    try:
        client_ip = request.headers.get('X-Real-IP')  # 也可以尝试 'X-Forwarded-For'
    except Exception as err:  # 捕获异常
        print(err)  # 打印异常参数
        res = MyResponse({"err": err}, False, "error").post()
        return res
    else:
        print("User IP Address:", client_ip)
        return handle_success(client_ip, "success")


# 获取原始jtl文件名，存储在json文件，执行测试结束后立刻调用
# 传参：projectName
# 返回： {
#             "jtlName": "TC01",
#             "reportIsExist": "False"
#         },
#         {
#             "jtlName": "TC02用户",
#             "reportIsExist": "False"
#         },
@report.route('/file/getJtlList', methods=['POST'])
def get_jtl_list():
    try:
        params = request.json
        root_path = get_global_config()['rootPath']
        jtl_path = os.path.join(root_path, params["projectName"], "jtl")
        report_info_path = os.path.join(root_path, params["projectName"], 'ReportInfo.json')

        # 获取生成的jtl文件名
        if os.path.exists(report_info_path):
            os.remove(report_info_path)

        with open(report_info_path, 'w', encoding='utf-8') as file:
            file.write("[]")
        if os.path.isdir(jtl_path):
            # 获取目录下所有文件名
            jtl_files = os.listdir(jtl_path)
            # 过滤以 kpi 或 error 结尾的文件
            filtered_jtl_files = [file for file in jtl_files if
                                  file.endswith('.jtl') and not (
                                          file.endswith('kpi.jtl') or file.endswith('error.jtl'))]
            jtl_data = []
            if filtered_jtl_files:
                # 生成 JSON 对象
                for file in filtered_jtl_files:
                    jtl_data.append({
                        "jtlName": file.replace('.jtl', ''),  # 去掉文件后缀
                        "reportIsExist": "False",  # 默认为 "False"
                    })
                # 将 JSON 对象写入文件
                with open(report_info_path, 'w') as json_file:
                    json.dump(jtl_data, json_file, indent=4, ensure_ascii=False)

    except Exception as err:  # 捕获异常
        print(err)  # 打印异常参数
        res = MyResponse({"err": err}, False, "error").post()
        return res
    else:
        return handle_success(jtl_data, "success")


# 获取reportInfo.json文件
# 传参：projectName
# 返回：    "data": [
#         {
#             "jtlName": "TC01_登录",
#             "reportIsExist": "True"
#         },
#         {
#             "jtlName": "TC02_用户",
#             "reportIsExist": "True"
#         }
#     ],
@report.route('/file/getReportJsonInfo', methods=['GET'])
def get_report_json_info():
    try:
        params = request.json
        root_path = get_global_config()['rootPath']
        json_file_path = os.path.join(root_path, params["projectName"], 'ReportInfo.json')

        if not os.path.exists(json_file_path):  # json文件在执行后生成，如果不存在表示没有执行过
            return handle_success("该项目没有执行记录", "该项目没有执行记录")
        with open(json_file_path, 'r') as file:
            data = json.load(file)
        if data == []:
            return handle_success("该项目没有生成jtl", "该项目没有生成jtl")
    except Exception as err:  # 捕获异常
        print(err)  # 打印异常参数
        res = MyResponse({"err": err}, False, "error").post()
        return res
    else:
        return handle_success(data, "success")
# @report.route('/file/IsReportExist', methods=['GET'])
# def is_report_exist():
#     try:
#         params = request.json
#         jtlName = params["jtlName"]
#         root_path = get_global_config()['rootPath']
#         PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))  # 根目录
#         report_file_path = os.path.join(PROJECT_ROOT, 'Solo\static\ReportInfo.json')
#
#
#
#
#     except Exception as err:  # 捕获异常
#         print(err)  # 打印异常参数
#         res = MyResponse({"err": err}, False, "error").post()
#         return res
#     else:
#         return handle_success(report_status, "success")

#生成原始报告
def generate_report(data):
    project_name = data["projectName"]
    root_path = get_global_config()['rootPath']
    jmeter_path = get_global_config()['jmeterPath']
    jmeter_bat_path = os.path.join(jmeter_path, 'bin/jmeter.bat')

    for jtl_name in  data["jtlName"]:
        print( data["jtlName"])
        report_save_path = os.path.join(root_path, project_name, "report", jtl_name)
        print(report_save_path)
        if os.path.exists(report_save_path):
            shutil.rmtree(report_save_path)
        os.makedirs(report_save_path)

        jtl_path = os.path.join(root_path, project_name, "jtl", jtl_name+'.jtl')
        commands = [jmeter_bat_path + ' -g ' + jtl_path + ' -e -o ' + report_save_path]
        print(commands)

        lock = threading.Lock()
        report_status[project_name] = {"running": True, "lock": lock, "start_time": time.time(), "process": None}

        with lock:
            for cmd in commands:
                process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
                                           stderr=subprocess.STDOUT, bufsize=1, text=True)
                print(report_status[project_name]["process"])

        del report_status[project_name]

# 生成原始报告
# 传参：projectName、jtlName
# 返回："success"
@report.route('/file/getOriginReport', methods=['POST'])
def get_origin_report():
    try:
        params = request.json
        root_path = get_global_config()['rootPath']
        report_info_path = os.path.join(root_path, params["projectName"], 'ReportInfo.json')
        project_name = params["projectName"]
        jtl_name = params["jtlName"]
        # jtl_names = [name for name in sencrioName]  # 处理为列表

        if project_name in report_status:
            return handle_exception("error", "该项目正在执行测试任务，请等待...")
        else:
            data = {"projectName": project_name, "jtlName": jtl_name}
            print(data)
            single_t = threading.Thread(target=generate_report, args=(data,))
            single_t.start()


            # 读取 JSON 文件
            with open(report_info_path, 'r') as file:
                report_data = json.load(file)

            # 更新对应的 reportIsExist 值
            for entry in report_data:
                if entry["jtlName"] in jtl_name:
                    entry["reportIsExist"] = "True"

            # 写回更新后的数据
            with open(report_info_path, 'w') as file:
                json.dump(report_data, file, ensure_ascii=False, indent=4)

    except Exception as err:
        print(err)
        res = MyResponse({"err": err}, False, "error").post()
        return res
    else:
        return handle_success("success", "success")

# 查看原始报告
# 传参：projectName
# 返回：["TC01.jtl","TC02用户.jtl"]
@report.route('/file/viewOriginReport', methods=['GET'])
def view_origin_report():
    try:
        params = request.json
        jtl_name = params["jtlName"]
        root_path = get_global_config()['rootPath']
        local_ip = get_local_ip()
        report_path = os.path.join(root_path, params["projectName"], "report", jtl_name)
        if os.path.exists(report_path):
            report_url = "http://" + local_ip + "/viewOriginReport/" + params["projectName"] + "/originReport"
    except Exception as err:  # 捕获异常
        print(err)  # 打印异常参数
        res = MyResponse({"err": err}, False, "error").post()
        return res
    else:
        return handle_success(report_url, "success")

# 下载原始报告
# 传参：projectName
# 返回：["TC01.jtl","TC02用户.jtl"]
@report.route('/file/downloadOriginReport', methods=['POST'])
def download_origin_report():
    try:
        params = request.json
        jtl_name = params["jtlName"]
        root_path = get_global_config()['rootPath']
        report_path = os.path.join(root_path, params["projectName"], "report", jtl_name)
        output_zip = os.path.join(root_path, params["projectName"], f"{jtl_name}_report.zip")
        compress_directory_to_zip(report_path, output_zip)
        res = send_file(output_zip, as_attachment=True, download_name=f"{jtl_name}_report.zip", mimetype="application/zip")
    except Exception as err:  # 捕获异常
        print(err)  # 打印异常参数
        res = MyResponse({"err": err}, False, "error").post()
        return res
    else:
        return res

